package ink.teamwork.battery.util;


import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.*;

public class BeanUtils {
    public static <T> T copy(Object source, Class<T> targetClass) {
        if (null == source) {
            return null;
        }
        T t;
        try {
            t = targetClass.getDeclaredConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                 InvocationTargetException e) {
            throw new RuntimeException(String.format("Create new instance of %s failed: %s", targetClass, e.getMessage()));
        }
        copy(source, t);
        return t;
    }

    public static <T> List<T> copy(List<?> sourceList, Class<T> targetClass) {
        if (CollectionUtils.isEmpty(sourceList)) {
            return Collections.emptyList();
        }
        List<T> resultList = new ArrayList<>(sourceList.size());
        for (Object o : sourceList) {
            T t;
            try {
                t = targetClass.getDeclaredConstructor().newInstance();
                copy(o, t);
                resultList.add(t);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return resultList;
    }

    public static void copy(Object source, Object target, String... ignore) {
        Objects.requireNonNull(source);
        Objects.requireNonNull(target);
        List<String> ignoreCopyProperties = new ArrayList<>();
        if (ignore != null) {
            ignoreCopyProperties.addAll(Arrays.asList(ignore));
        }
        List<Field> fields = new ArrayList<>();

        Class<?> temp = source.getClass();
        while (temp != null && !temp.getName().equalsIgnoreCase("java.lang.object")) {
            fields.addAll(Arrays.asList(temp.getDeclaredFields()));
            temp = temp.getSuperclass();
        }
        fields.forEach(field -> {
            Object fieldValue = null;
            boolean isStatic = Modifier.isStatic(field.getModifiers());
            if (!field.canAccess(isStatic ? null : source)) {
                field.setAccessible(true);
            }
            try {
                // 根据字段类型调整 get 参数
                fieldValue = isStatic ? field.get(null) : field.get(source);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } finally {
                field.setAccessible(false); // 确保恢复字段的可访问性
            }
            // 静态字段不应加入 ignoreCopyProperties
            if (!isStatic && fieldValue == null) {
                ignoreCopyProperties.add(field.getName());
            }
        });
        org.springframework.beans.BeanUtils.copyProperties(source, target, ignoreCopyProperties.toArray(new String[]{}));
    }

}
